﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using Metaspec;

// Shared assembly example.

namespace SharedAssemblyExample
{
	class Program
	{
		static void Main(string[] args)
		{
			const int max_projects = 100;

			//creating solution
			ISolution solution = ISolutionFactory.create();

			//adding assemblies
			string assembly_path = Assembly.GetAssembly(typeof(object)).Location;
			byte[] assembly_buffer = File.ReadAllBytes(assembly_path);
			IExternalAssemblyModule module = IExternalAssemblyModuleFactory.create(assembly_buffer, assembly_path);
			solution.addExternalAssemblyModules(new IExternalAssemblyModule[] { module }, true, null);
			IExternalAssembly assembly = module.getExternalAssembly();

			for (int i = 0; i != max_projects; ++i)
			{
				//creating project
				ICsProject project = ICsProjectFactory.create(project_namespace.pn_project_namespace);
				project.setBuildEntityModel(true);

				//adding C# file
				string directory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\..");
				string path = Path.Combine(directory, "Project1.cs");
				char[] buffer = File.ReadAllText(path).ToCharArray();
				ICsFile file = ICsFileFactory.create(buffer, path);
				project.addFiles(file);
				project.addAssemblyReferences(new ExternalAssemblyReference(assembly));

				//adding project to solution
				solution.addProjects(project);
			}

			solution.parse();

			//checking
			foreach (ICsProject project in solution.getProjects())
			{
				ICsFile file = project.getFiles()[0];
				CsCompilationUnit unit = file.getCompilationUnit();

				CsNamespace ns = (CsNamespace)unit.declarations[0];
				CsClass c = (CsClass)ns.member_declarations[0];
				CsMethod m = (CsMethod)c.member_declarations[0];
				CsBlock body = m.definition;
				CsLocalVariableDeclaration decl = (CsLocalVariableDeclaration)((CsDeclarationStatement)body.statements[0]).declaration;
				CsEntity entity = getEntity(project.getNamespace(), "System", "Object");
				Debug.Assert(decl.type.entity_typeref.type == cs_entity_type.et_object);
				Debug.Assert(decl.type.entity_typeref.u == entity);
				Debug.Assert(((CsEntity)decl.type.entity_typeref.u).assembly == assembly.getAssemblyEntity());
			}
		}

		static CsEntity getEntity(CsScopeEntity scope, params string[] names)
		{
			CsEntity entity = null;
			for (int i = 0; i != names.Length; ++i)
			{
				entity = scope.scope_table.get_single_id(names[i]);
				if (i != names.Length - 1)
				{
					scope = (CsScopeEntity)entity;
				}
			}
			return entity;
		}
	}
}
